package it.uniroma2.art.stontoling.servlet;

import it.uniroma2.art.lw.exceptions.LinguisticInterfaceLoadException;
import it.uniroma2.art.lw.exceptions.PropertyNotFoundException;
import it.uniroma2.art.lw.manager.LinguisticWatermarkManager;
import it.uniroma2.art.lw.model.LingModel;
import it.uniroma2.art.lw.model.LinguisticResource;
//import it.uniroma2.art.lw.model.objects.ConceptualizedLR;
import it.uniroma2.art.lw.model.objects.ExclusiveExplorationObject;
import it.uniroma2.art.lw.model.objects.LIFactory;
import it.uniroma2.art.lw.model.objects.LexicalRelation;
import it.uniroma2.art.lw.model.objects.LinguisticInterface;
import it.uniroma2.art.lw.model.objects.SearchFilter;
import it.uniroma2.art.lw.model.objects.SearchStrategy;
import it.uniroma2.art.lw.model.objects.SearchWord;
import it.uniroma2.art.lw.model.objects.SemIndexRetrievalException;
import it.uniroma2.art.lw.model.objects.SemanticIndex;
import it.uniroma2.art.lw.model.objects.SemanticRelation;
import it.uniroma2.art.lw.model.objects.TaxonomicalLR;
import it.uniroma2.art.ontoling.OntoLingCore;
import it.uniroma2.art.ontoling.exceptions.OntoLingInitializationException;
import it.uniroma2.art.ontoling.exceptions.UIActionException;
import it.uniroma2.art.ontoling.ui.UIActionList;
import it.uniroma2.art.ontoling.ui.UIReasoner;
import it.uniroma2.art.owlart.exceptions.ModelAccessException;
import it.uniroma2.art.owlart.exceptions.ModelUpdateException;
import it.uniroma2.art.owlart.model.ARTResource;
import it.uniroma2.art.owlart.model.ARTURIResource;
import it.uniroma2.art.owlart.models.DirectReasoning;
import it.uniroma2.art.owlart.models.OWLModel;
import it.uniroma2.art.owlart.models.RDFSModel;
import it.uniroma2.art.owlart.navigation.RDFIterator;
import it.uniroma2.art.owlart.utilities.ModelUtilities;
import it.uniroma2.art.owlart.vocabulary.RDFResourceRolesEnum;
//import it.uniroma2.art.semanticturkey.plugin.extpts.CXSL;
import it.uniroma2.art.semanticturkey.exceptions.HTTPParameterUnspecifiedException;
import it.uniroma2.art.semanticturkey.exceptions.NonExistingRDFResourceException;
import it.uniroma2.art.semanticturkey.ontology.utilities.RDFXMLHelp;
import it.uniroma2.art.semanticturkey.ontology.utilities.STRDFNodeFactory;
import it.uniroma2.art.semanticturkey.ontology.utilities.STRDFResource;
import it.uniroma2.art.semanticturkey.plugin.extpts.PluginServiceAdapter;
//import it.uniroma2.art.semanticturkey.plugin.extpts.ServiceAdapter;
import it.uniroma2.art.semanticturkey.project.ProjectManager;
import it.uniroma2.art.semanticturkey.resources.Resources;
import it.uniroma2.art.semanticturkey.servlet.Response;
//import it.uniroma2.art.semanticturkey.servlet.ResponseREPLY;
import it.uniroma2.art.semanticturkey.servlet.XMLResponseREPLY;
//import it.uniroma2.art.semanticturkey.servlet.ResponseACTION;
import it.uniroma2.art.semanticturkey.servlet.ServletUtilities;
import it.uniroma2.art.semanticturkey.servlet.ServiceVocabulary.RepliesStatus;
import it.uniroma2.art.semanticturkey.servlet.ServiceVocabulary.SerializationType;
import it.uniroma2.art.semanticturkey.servlet.main.Cls;
import it.uniroma2.art.semanticturkey.utilities.XMLHelp;
import it.uniroma2.art.stontoling.plugin.STOntoLingPlugin;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.w3c.dom.Element;


//public class STOntoLing extends ServiceAdapter{
public class STOntoLing extends PluginServiceAdapter{
	
	final String exstName = "stontoling@art.uniroma2.it";
	
	protected static Log logger = LogFactory.getLog(STOntoLing.class);
	
	public static final String startOntoLingRequest = "startOntoLing";
    public static final String isOntoLingUpRequest = "isOntoLingUp";
    public static final String getLoadedLIntRequest = "getLoadedLInt";
    public static final String selectLingResRequest = "selectLingRes";
    public static final String searchWordRequest = "searchWord";
    public static final String searchLemmaRequest = "searchLemma";
    public static final String lexRelRequest = "lexRel";
    public static final String semRelRequest = "semRel";
    public static final String getPossibleLIntRequest = "getPossibleLInt";
    public static final String loadLingResRequest = "loadLingRes";
    public static final String unloadLingResRequest = "unloadLingRes";
    public static final String addSubConceptsRequest = "addSubConcepts";
    
    public static final String getLingInterfaceListRequest = "getLingInterfacesList";
    public static final String getLingInstanceListRequest = "getLingInstancesList";
    public static final String updateLingInstanceIdRequest = "updateLingInstanceId";
    public static final String updateLingInstancePropValueRequest = "updateLingInstancePropValue";
    public static final String createLingInstanceRequest = "createLingInstance";
    public static final String removeLingInstanceRequest = "removeLingInstance";
    
    
    
    
	private OntoLingCore ontLingCore;
	private LinguisticInterface lInst;
	private UIReasoner uiReasoner;
	private STOntoLingGUIAdapter guiAdapter;
	
	private boolean ontoLingUp = false;
	private boolean ontoLingStarting = false;

	
	public STOntoLing(String id, STOntoLingPlugin plugin){
		super(id, plugin);
	}
	

	@Override
	public Response getResponse() {
        String request = setHttpPar("request");
		if(request == null){
			return ServletUtilities.getService().createExceptionResponse(request, 
					"parameter request is mandatory");
        }
        else if( request.equals(startOntoLingRequest) ){
        	String firstStart =setHttpPar("firstStart"); //TODO check what happen if there is no value
        	return startSTOntoLing(firstStart); 
        }
        else if(request.equals(isOntoLingUpRequest)){
        	return isOntoLingUp();
        }
        else if (request.equals(getLoadedLIntRequest)) {
        	return getLoadedRes();
        }
        else if(request.equals(selectLingResRequest)){
        	String selResId = setHttpPar("lResId");
        	return selectRes(selResId);
        }
        else if(request.equals(searchWordRequest)){
        	String word = setHttpPar("word");
        	String srchStr = setHttpPar("srchStr");
        	int numFilters = Integer.parseInt(setHttpPar("numFilters"));
        	//ArrayList <String>filtersList = new ArrayList<String>();
        	
        	if(numFilters > 0){
        		String filtersList;
        		filtersList = setHttpPar("filters");
        		return searchWord(word, srchStr, filtersList);
        	}
        	else{
        		return searchWord(word, srchStr, null);
        	}
        }
        else if(request.equals(searchLemmaRequest)){
        	String lemma = setHttpPar("lemma");
        	return searchLemma(lemma);
        }
        else if(request.equals(lexRelRequest)){
        	String lemma = setHttpPar("lemma"); 
        	String semex = setHttpPar("semex");
        	String lexRel = setHttpPar("lexRel");
        	return lexicalRelation(lemma, semex, lexRel);
        }
        else if(request.equals(semRelRequest)){
        	String semex = setHttpPar("semex");
        	String semRel = setHttpPar("semRel");
        	return semanticRelation(semex, semRel);
        }
        else if(request.equals(getPossibleLIntRequest)){
        	return getPossibleRes();
        }
        else if(request.equals(loadLingResRequest)){
        	String lRedId = setHttpPar("lResId");
        	return loadLingRes(lRedId);
        }
        else if(request.equals(unloadLingResRequest)){
        	String lRedId = setHttpPar("lResId");
        	return unloadLingRes(lRedId);
        }
        else if(request.equals(addSubConceptsRequest)){
        	String semex = setHttpPar("semex");
        	String conceptId = setHttpPar("conceptId");
        	String type = setHttpPar("type");
        	return addSubConcept(semex, conceptId, type);
        }
        else if(request.equals(getLingInterfaceListRequest)){
        	return getLingInterfaceList();
        }
        else if(request.equals(getLingInstanceListRequest)){
        	String interfaceId = setHttpPar("interfaceId");
        	return getLingInstanceList(interfaceId);
        }
        else if(request.equals(updateLingInstanceIdRequest)) {
        	String oldInstanceId = setHttpPar("oldInstanceId");
        	String newInstanceId = setHttpPar("newInstanceId");
        	return updateLingInstanceId(oldInstanceId, newInstanceId);
        }
        else if(request.equals(updateLingInstancePropValueRequest)) {
        	String instanceId = setHttpPar("instanceId");
        	String interfaceId = setHttpPar("interfaceId");
        	String propId = setHttpPar("propId");
        	String propValue = setHttpPar("propValue");
        	String isIntPropString = setHttpPar("isIntProp");
        	boolean isIntProp = false;
        	if(isIntPropString.equals("true"))
        		isIntProp = true;
        	return updateLingInstancePropValue(instanceId, interfaceId, propId, propValue, isIntProp);
        }
        else if(request.equals(createLingInstanceRequest)) {
        	String interfaceId = setHttpPar("interfaceId");
        	String instanceId = setHttpPar("instanceId");
        	return createLingInstance(instanceId, interfaceId);
        }
        else if(request.equals(removeLingInstanceRequest)) {
        	String interfaceId = setHttpPar("interfaceId");
        	String instanceId = setHttpPar("instanceId");
        	return removeLingInstance(instanceId, interfaceId);
        }
        else 
        	return ServletUtilities.getService().createExceptionResponse(request, 
        			"parameter request is not suppported");
    }
	
	

	private Response startSTOntoLing(String firstStart){
		XMLResponseREPLY response = null;
		
		String fs = System.getProperty("file.separator");
		//File oSGiDir = new File(Resources.getSemTurkeyDataDir()+"/felixSTOntoLing");
		
		File oSGiDir = new File(Resources.getExtensionPath().getAbsolutePath()+fs+".."
				+fs+exstName+fs+"OSGi_stOL");
		File configFile = new File(Resources.getExtensionPath().getAbsolutePath()+fs+".."
				+fs+exstName+fs+"extensions"+fs+"properties"+fs+"LWConfig.xml");
        //String rootBundleDir = (new File(Resources.getExtensionPath())).getParent();
        String rootBundleDir = Resources.getExtensionPath().getParent();
        
        try {
        	ontoLingStarting = true;
        	logger.debug("firstStart stOntoLing= "+firstStart); 
        	if(firstStart.compareTo("true") == 0){
        		Map <String, String> placeholderIdValueMap = new HashMap<String, String>();
        		//add to the map the placeholders with their values
        		placeholderIdValueMap.put("%dirRes%", Resources.getSemTurkeyDataDir().getAbsolutePath()); 
        		logger.debug("%dirRes% = "+ Resources.getSemTurkeyDataDir());
        		logger.debug("configFile = "+ configFile);
        		ontLingCore = OntoLingCore.initialize(oSGiDir, rootBundleDir, true, configFile, 
        				placeholderIdValueMap);
        	}
        	else{
        		ontLingCore = OntoLingCore.initialize(oSGiDir, rootBundleDir, true, configFile);
        	}

        	uiReasoner = ontLingCore.getUIReasoner();
        	guiAdapter = new STOntoLingGUIAdapter();
        	ontLingCore.setGUIAdapter(guiAdapter);
        	
        	ontoLingUp = true;
        	response = ServletUtilities.getService().createReplyResponse(startOntoLingRequest, 
        			RepliesStatus.ok);
        } catch (OntoLingInitializationException e) {
        	response = ServletUtilities.getService().createReplyResponse(startOntoLingRequest, 
        			RepliesStatus.fail);
        }
        return response;
	}
	
	
	private Response isOntoLingUp(){
		XMLResponseREPLY response;
		if(ontoLingStarting == true) {
			response = ServletUtilities.getService().createReplyResponse(isOntoLingUpRequest, 
					RepliesStatus.ok);
			Element dataElement = response.getDataElement();
			Element infoStatus = XMLHelp.newElement(dataElement, "infoStatus");
			if(ontoLingUp == true)
				infoStatus.setAttribute("info", "ok");
			else
				infoStatus.setAttribute("info", "problems");
		}
		else{
			response = ServletUtilities.getService().createReplyResponse(isOntoLingUpRequest, 
					RepliesStatus.fail);
			Element dataElement = response.getDataElement();
			Element infoStatus = XMLHelp.newElement(dataElement, "infoStatus");
			infoStatus.setAttribute("info", "fail");
		}
		return response;
	}
	
	
	private Response getLoadedRes(){
		XMLResponseREPLY response = ServletUtilities.getService().createReplyResponse(getLoadedLIntRequest, 
				RepliesStatus.ok);
		Element dataElement = response.getDataElement();
		
        Collection <LinguisticResource> lResList = 
        		LinguisticWatermarkManager.getLinguisticModel().getLinguisticResources();
        for(LinguisticResource lRes : lResList){
        	if(lRes.getLinguisticInterface() != null) {
	    		Element loadedResElement = XMLHelp.newElement(dataElement, "loadedRes");
        		loadedResElement.setAttribute("resId", lRes.getId());
        		loadedResElement.setAttribute("langLRes", lRes.getLinguisticInterface().getLanguage());
	    		loadedResElement.setAttribute("interfaceId", lRes.getLinguisticInterfaceID());
	    	}
    	}
		return response;
	}
	
	
	
	private Response selectRes(String selResId) {
		XMLResponseREPLY response = ServletUtilities.getService().createReplyResponse(selectLingResRequest, 
				RepliesStatus.ok);
		Element dataElement = response.getDataElement();
		
		LinguisticWatermarkManager.setLoadedInterface(selResId);
        LinguisticWatermarkManager.save();
        lInst = LinguisticWatermarkManager.getSelectedInterface();
        UIActionList al = uiReasoner.initialize(lInst);
        guiAdapter.handleUIActionList(al);
        
        HashMap<Class<? extends ExclusiveExplorationObject>, Collection<String>> relationExplorer 
        		= guiAdapter.getRelationExplorers();
        
        Element selResNode = XMLHelp.newElement(dataElement, "selectedResource");
        selResNode.setAttribute("selResId", selResId);
        
        Element semRelListNode = XMLHelp.newElement(dataElement, "semanticRelations");
        Collection<String>semRelList = relationExplorer.get(SemanticRelation.class);
        Iterator<String> iter = semRelList.iterator();
        while(iter.hasNext()) {
        	Element semRelNode = XMLHelp.newElement(semRelListNode, "semRelId");
        	semRelNode.setAttribute("semRelId", iter.next());
        }
        
        Collection<String>lexRelList = relationExplorer.get(LexicalRelation.class);
        iter = lexRelList.iterator();
        
        Element lexRelListNode = XMLHelp.newElement(dataElement, "lexicalRelations");
        while(iter.hasNext()) {
        	Element lexRelNode = XMLHelp.newElement(lexRelListNode, "lexRelId");
        	lexRelNode.setAttribute("lexRelId", iter.next());
        }
        Collection<String>srchStrList = relationExplorer.get(SearchStrategy.class);
        iter = srchStrList.iterator();
        
        Element srchStrListNode = XMLHelp.newElement(dataElement, "searchStrategies");
        while(iter.hasNext()) {
        	Element srchStrNode = XMLHelp.newElement(srchStrListNode, "srchStrId");
        	srchStrNode.setAttribute("srchStrId", iter.next());
        }

        Element srchFilterListNode = XMLHelp.newElement(dataElement, "searchFilters");
        Collection<SearchFilter> searchFilterList = guiAdapter.getSearchFilterList();
    	Iterator<SearchFilter> iterFilter = searchFilterList.iterator();
        while(iterFilter.hasNext()){
        	SearchFilter srchFilter = iterFilter.next();
        	Element srchFilterNode = XMLHelp.newElement(srchFilterListNode, "srchFilterId");
        	srchFilterNode.setAttribute("srchFilterId", srchFilter.getName());
        	srchFilterNode.setAttribute("active", srchFilter.isActive()+"");
        }
                
        HashMap<String, Collection<STOntoLingGUIAdapter.CtxMenuItem>> ctxMenuItemMap = 
        		guiAdapter.getCtxMenuLabels();
        Element ctxMenuNode = XMLHelp.newElement(dataElement, "ctxMenu");
        
        Collection<STOntoLingGUIAdapter.CtxMenuItem>ctxMenuItemClassList = ctxMenuItemMap.get("class");
        Iterator <STOntoLingGUIAdapter.CtxMenuItem>iterClass = ctxMenuItemClassList.iterator();
        
        Element ctxMenuClassNode = XMLHelp.newElement(ctxMenuNode, "ctxMenuClass");
        while(iterClass.hasNext()){
        	STOntoLingGUIAdapter.CtxMenuItem ctxMenuItem = iterClass.next();
        	Element ctxMenuItemNode = XMLHelp.newElement(ctxMenuClassNode, "ctxMenuClassItem");
        	ctxMenuItemNode.setAttribute("name", ctxMenuItem.getName());
        	ctxMenuItemNode.setAttribute("label", ctxMenuItem.getLabel());
        }
        
        Collection<STOntoLingGUIAdapter.CtxMenuItem>ctxMenuItemPropertyList = ctxMenuItemMap.get("property");
        Iterator <STOntoLingGUIAdapter.CtxMenuItem>iterProperty = ctxMenuItemPropertyList.iterator();
        Element ctxMenuPropertyNode = XMLHelp.newElement(ctxMenuNode, "ctxMenuProperty");
        while(iterProperty.hasNext()){
        	STOntoLingGUIAdapter.CtxMenuItem ctxMenuItem = iterProperty.next();
        	Element ctxMenuItemNode = XMLHelp.newElement(ctxMenuPropertyNode, "ctxMenuPropertyItem");
        	ctxMenuItemNode.setAttribute("name", ctxMenuItem.getName());
        	ctxMenuItemNode.setAttribute("label", ctxMenuItem.getLabel());
        }
        return response;
	}
	
	private Response searchWord(String word, String srchStr, String filtersList) {
		XMLResponseREPLY response = ServletUtilities.getService().createReplyResponse(searchWordRequest, 
				RepliesStatus.ok);
		Element dataElement = response.getDataElement();
		Element searchWordNode = XMLHelp.newElement(dataElement, "search");
		searchWordNode.setAttribute("word", word);
        searchWordNode.setAttribute("srchStr", srchStr);
        
        String[] filtersArray = new String[0];
        if(filtersList != null){
        	filtersArray = filtersList.split("\\|_\\|");
        }
        searchWordNode.setAttribute("filterListNum", filtersArray.length+"");
        
        
        SearchFilter []searchFilterArray  = new SearchFilter[filtersArray.length];
        for(int i=0; i<filtersArray.length; ++i){
        	searchWordNode.setAttribute("filter"+i, filtersArray[i]);
        	searchFilterArray[i] = new SearchFilter(filtersArray[i]);
        }
        
		
		try {
			UIActionList al = uiReasoner.notifiedSearchField(word, srchStr, searchFilterArray);
			guiAdapter.handleUIActionList(al);
			Collection<SearchWord> searchWordList = guiAdapter.getSearchWordList();
			Iterator <SearchWord>iterSearchWord = searchWordList.iterator();
			
			Element resultSearchWordListNode = XMLHelp.newElement(dataElement, "searchWordList");
			while(iterSearchWord.hasNext()){
				SearchWord searchWord = iterSearchWord.next();
				Element resultSearchWordNode = XMLHelp.newElement(resultSearchWordListNode, "searchWord");
				resultSearchWordNode.setAttribute("value", searchWord.getName());
			}
		} catch (UIActionException e) {
			return servletUtilities.createExceptionResponse(getLingInterfaceListRequest, 
					"There was a problem doing the "+srchStr+" search using the word "+word);
		}
		
		return response;
	}
	
	// TODO questi metodo funziona solo per risorse con glosse e concetti o solo con concetti, ma non per quelle flat
	// visto che quelle flat (mai sperimentate), non hanno una ResultTable
	// per comprendere la differenza vedere in UIReasoner.java i seguenti metodi:
	// notifiedSearchTerm_CG  (ha al.addResultTableAction();)
	// notifiedSearchTerm_C (ha al.addResultTableAction();)
	// notifiedSearchTerm_F (ha al.addSetSynonymsListAction)
	private Response searchLemma(String lemma) {
		XMLResponseREPLY response = ServletUtilities.getService().createReplyResponse(searchLemmaRequest, 
				RepliesStatus.ok);
		Element dataElement = response.getDataElement();
		
		try {
        	UIActionList al = uiReasoner.notifiedSearchWord(new SearchWord(lemma));
        	guiAdapter.handleUIActionList(al);
        	 Element searchLemmaNode = XMLHelp.newElement(dataElement, "searchLemma");
             searchLemmaNode.setAttribute("lemma", lemma);
             
             prepareTableData(dataElement);
        } catch (UIActionException e) {
        	return servletUtilities.createExceptionResponse(getLingInterfaceListRequest, 
        			"There was a problem searching the lemma "+lemma);
		}	
       
        
        return response;
	}
	
	private Response lexicalRelation(String lemma, String semex, String lexRel) {
		XMLResponseREPLY response = ServletUtilities.getService().createReplyResponse(semRelRequest, 
				RepliesStatus.ok);
		Element dataElement = response.getDataElement();
		
        try {
        	UIActionList al = uiReasoner.notifiedLexicalRelation(lemma, semex, lexRel);
			guiAdapter.handleUIActionList(al);
			Element searchLemmaNode = XMLHelp.newElement(dataElement, "lexicalRelation");
	        searchLemmaNode.setAttribute("lemma", lemma);
	        searchLemmaNode.setAttribute("semex", semex);
	        searchLemmaNode.setAttribute("lexRel", lexRel);
	        
	        prepareTableData(dataElement);
		} catch (UIActionException e) {
			return servletUtilities.createExceptionResponse(getLingInterfaceListRequest, e.getMessage());
		}
		
        return response;
	}
	
	private Response semanticRelation(String semex, String semRel) {
		XMLResponseREPLY response = ServletUtilities.getService().createReplyResponse(semRelRequest, 
				RepliesStatus.ok);
		Element dataElement = response.getDataElement();
        
        try {
        	UIActionList al = uiReasoner.notifiedSemanticRelation(semex, semRel);
			guiAdapter.handleUIActionList(al);
			Element searchLemmaNode = XMLHelp.newElement(dataElement, "semanticRelation");
	        searchLemmaNode.setAttribute("semex", semex);
	        searchLemmaNode.setAttribute("lexRel", semRel);
	        
	        prepareTableData(dataElement);
		} catch (UIActionException e) {
			return servletUtilities.createExceptionResponse(getLingInterfaceListRequest, 
					"There was a problem with the semantic relation "+semRel);
		}
		
        return response;
	}
	
	
	private void prepareTableData(Element dataElement) throws UIActionException{
		
		Element resultTableNode = XMLHelp.newElement(dataElement, "resultTable");
	
			
		Collection<String[]> resultTable = guiAdapter.getResultTable();
		if (resultTable != null) { // caso Concept [and Gloss]
			Iterator<String[]> iterResultTable = resultTable.iterator();

			while (iterResultTable.hasNext()) {
				Element tableRowNode = XMLHelp.newElement(resultTableNode, "tableRow");
				String[] valuesRow = iterResultTable.next();

				Element tableCellIDNode = XMLHelp.newElement(tableRowNode, "tableCellID");
				tableCellIDNode.setAttribute("value", valuesRow[0]);

				Element tableCellWordNode = XMLHelp.newElement(tableRowNode, "tableCellWord");
				tableCellWordNode.setAttribute("value", valuesRow[1]);

				Element tableCellDescNode = XMLHelp.newElement(tableRowNode, "tableCellDesc");
				tableCellDescNode.setAttribute("value", valuesRow[2]);

				// add to the result xml also the synonyms list
				UIActionList al = uiReasoner.notifiedSelectedRowOnResultsTable(valuesRow[0], valuesRow[1]);
				guiAdapter.handleUIActionList(al);
				Collection<String> synonymsList = guiAdapter.getSynonymsList();
				Iterator<String> iterSynonymsList = synonymsList.iterator();
				Element synonymsListNode = XMLHelp.newElement(tableRowNode, "synonymsList");
				while (iterSynonymsList.hasNext()) {
					String synonym = iterSynonymsList.next();
					Element synonymNode = XMLHelp.newElement(synonymsListNode, "synonym");
					synonymNode.setAttribute("value", synonym);
				}
			}
		} else {
			//Flat case
		}
		
	}
	
	private Response getPossibleRes(){
		XMLResponseREPLY response = ServletUtilities.getService().createReplyResponse(getPossibleLIntRequest, 
				RepliesStatus.ok);
		Element dataElement = response.getDataElement();
		        
        Collection<LinguisticResource> lingResList 
        		= LinguisticWatermarkManager.getLinguisticModel().getLinguisticResources();
        Element possInstListNode = XMLHelp.newElement(dataElement, "possInstList");
        for(LinguisticResource lRes : lingResList){
        	if(lRes.getLinguisticInterfaceFactory() != null){
        		String lResId = lRes.getId();
        		String interfaceId = lRes.getLinguisticInterfaceID();
        		boolean loaded = (lRes.getLinguisticInterface() != null);
        		Element possInstNode = XMLHelp.newElement(possInstListNode, "possInst");
        		possInstNode.setAttribute("resId", lResId);
        		possInstNode.setAttribute("interfaceId", interfaceId);
        		possInstNode.setAttribute("loaded", loaded+"");
        	}
        }
        return response;
	}
	
	private Response loadLingRes(String lResId){
		XMLResponseREPLY response;
		
        LinguisticResource lRes 
        		= LinguisticWatermarkManager.getLinguisticModel().getLinguisticResource(lResId);
        try {
			lRes.loadLinguisticInterface();
			LinguisticWatermarkManager.save();
			response = ServletUtilities.getService().createReplyResponse(loadLingResRequest, 
					RepliesStatus.ok);
		} catch (LinguisticInterfaceLoadException e) {
			lRes.unloadLinguisticInterface();
			response = ServletUtilities.getService().createReplyResponse(loadLingResRequest, 
					RepliesStatus.fail);
		}
		return response;
	}
	
	private Response unloadLingRes(String lResId){
		XMLResponseREPLY response;
		
        LinguisticResource lRes 
        		= LinguisticWatermarkManager.getLinguisticModel().getLinguisticResource(lResId);
        lRes.unloadLinguisticInterface();
        LinguisticWatermarkManager.save();
		
        response = ServletUtilities.getService().createReplyResponse(unloadLingResRequest, RepliesStatus.ok);
        return response;
	}
	
	private Response addSubConcept(String semex, String conceptId, String propertyType) {
		ArrayList <String> alredyExistingResources = new ArrayList<String>();
		ArrayList <String> addedResources = new ArrayList<String>();
		
		
		// first get from the linguistic resource all the direct descendants of the given semex, then add one 
		// by one to the ontology
		try {
			TaxonomicalLR lint = (TaxonomicalLR) LinguisticWatermarkManager.getSelectedInterface();
			SemanticIndex c = lint.getConcept(semex);
			Collection <SemanticIndex>senses = lint.getDirectDescendants(c);
			Iterator <SemanticIndex>iterator = senses.iterator();
			OWLModel ontModel = ProjectManager.getCurrentProject().getOWLModel();
			String superResourceURI = ontModel.expandQName(conceptId);
			ARTResource superResource = ontModel.createURIResource(superResourceURI);
			
			ARTResource[] graphs = getUserNamedGraphs();
			ARTResource wgraph = getWorkingGraph();
			
			XMLResponseREPLY response = createReplyResponse(RepliesStatus.ok);
			Element dataElement = response.getDataElement();
			
			Element conceptElement = XMLHelp.newElement(dataElement, "Concept");
			
			Element subConceptElement = XMLHelp.newElement(dataElement, "SubConcepts");
			
			Collection<STRDFResource> concepts = STRDFNodeFactory.createEmptyResourceCollection();
			while (iterator.hasNext()) {
				String[] labels = lint.getConceptLexicals(iterator.next());
				//create a class in the ontology using as id labels[0]
				String newResourceURI = ontModel.expandQName(labels[0]);
				
				ARTURIResource res = ontModel.createURIResource(newResourceURI);
				boolean exists = ModelUtilities.checkExistingResource(ontModel, res);
				if (exists) {
					alredyExistingResources.add(labels[0]);
					logger.error("there is a resource with the same name!");
				}
				else{
					addedResources.add(labels[0]);
					
					if(propertyType.equals("class")) {
						logger.debug("trying to create class: " + newResourceURI + " as subClassOf: " 
								+ superResource);
							
						ontModel.addClass(newResourceURI);
						ontModel.addSuperClass(res, superResource);
					}
					else{
						logger.debug("trying to create property: " + newResourceURI + " as subPropertyOf: " 
								+ superResource);

						if (propertyType.equals("rdf:Property"))
							ontModel.addProperty(newResourceURI, (ARTURIResource)superResource);
						else if (propertyType.equals("owl:ObjectProperty"))
							ontModel.addObjectProperty(newResourceURI, (ARTURIResource)superResource);
						else if (propertyType.equals("owl:DatatypeProperty"))
							ontModel.addDatatypeProperty(newResourceURI, (ARTURIResource)superResource);
						else if (propertyType.equals("owl:AnnotationProperty"))
							ontModel.addAnnotationProperty(newResourceURI, (ARTURIResource)superResource);
					}
					//add to the created resource one rdfs:label property for every labels in the concept 
					//of the linguistic resource
					ARTURIResource property = ontModel.createURIResource(ontModel.expandQName("rdfs:label"));
					for(int i=1; i<labels.length; ++i){
						ontModel.instantiateAnnotationProperty(res, property, labels[i], null);
					}
				}
				
			}
			Iterator<String> iterAR = addedResources.iterator();
	        while(iterAR.hasNext()) {
	        	ARTResource addedClass = retrieveExistingResource(ontModel, iterAR.next(), graphs);
	        	STRDFResource stClass = STRDFNodeFactory.createSTRDFResource(ontModel, addedClass,
	        			ModelUtilities.getResourceRole(addedClass, ontModel), 
	        			servletUtilities.checkWritable(ontModel, addedClass, wgraph), false);
	        	
	        	Cls.decorateForTreeView(ontModel, stClass, graphs);
	        
	        	Cls.setRendering(ontModel, stClass, null, null, graphs);
	        	
	        	
	        	concepts.add(stClass);
	        }
	        
	        STRDFResource stParentConcept = STRDFNodeFactory.createSTRDFResource(ontModel, superResource,
					ModelUtilities.getResourceRole(superResource, ontModel), 
					servletUtilities.checkWritable(ontModel, superResource, wgraph), false);
	        Cls.decorateForTreeView(ontModel, stParentConcept, graphs);
	        Cls.setRendering(ontModel, stParentConcept, null, null, graphs);
	        
	        RDFXMLHelp.addRDFNode(conceptElement, stParentConcept);
	        
	        RDFXMLHelp.addRDFNodes(subConceptElement, concepts);
	        
			
			return response;
		} catch (SemIndexRetrievalException e) {
			return logAndSendException(e);
			//return servletUtilities.createExceptionResponse(addSubConceptsRequest, e.getMessage());
		} catch (ModelAccessException e) {
			return logAndSendException(e);
			//return servletUtilities.createExceptionResponse(addSubConceptsRequest, e);
		} catch (ModelUpdateException e) {
			return logAndSendException(e);
			//return servletUtilities.createExceptionResponse(addSubConceptsRequest, e);
		} catch (NonExistingRDFResourceException e) {
			return logAndSendException(e);
		}
		
		//new Version
		
		
		
		// old Version
		/*response = ServletUtilities.getService().createReplyResponse(addSubConceptsRequest, RepliesStatus.ok);
		Element dataElement = response.getDataElement();
		
		Element parentResourceNode = XMLHelp.newElement(dataElement, "parentResource");
		parentResourceNode.setAttribute("name", conceptId);
		
		Element addedResourceNode = XMLHelp.newElement(dataElement, "addedResources");
		Iterator<String> iterAR = addedResources.iterator();
        while(iterAR.hasNext()) {
        	Element semRelNode = XMLHelp.newElement(addedResourceNode, "resource");
        	semRelNode.setAttribute("name", iterAR.next());
        }
        
        Element existingResourceNode = XMLHelp.newElement(dataElement, "existingResources");
        Iterator<String> iterER = alredyExistingResources.iterator();
        while(iterER.hasNext()) {
        	Element semRelNode = XMLHelp.newElement(existingResourceNode, "resource");
        	semRelNode.setAttribute("name", iterER.next());
        }
        return response;
        */
		
        
	}
	
	private Response getLingInterfaceList(){
		XMLResponseREPLY response = ServletUtilities.getService().createReplyResponse(
				getLingInterfaceListRequest, RepliesStatus.ok);
		LingModel lingModel = LinguisticWatermarkManager.getLinguisticModel();
		Collection<String>interfaceElementIdsVector = lingModel.getLinguisticInterfacesIDs();
		Element dataElement = response.getDataElement();
		for(String interfaceId : interfaceElementIdsVector){
			Element node = XMLHelp.newElement(dataElement, "lingInterface");
			node.setAttribute("interfaceId", interfaceId);
		}
		return response;
	}
	
	private Response getLingInstanceList(String interfaceId){
		XMLResponseREPLY response;
		try{
			response = ServletUtilities.getService().createReplyResponse(getLingInterfaceListRequest, 
					RepliesStatus.ok);
			Element dataElement = response.getDataElement();
			LingModel lingModel = LinguisticWatermarkManager.getLinguisticModel();
			if(lingModel.getLinguisticResourceType(interfaceId) == null)
				return servletUtilities.createExceptionResponse(getLingInterfaceListRequest, 
						"There is no interface with id  "+interfaceId);
			LIFactory liFact = lingModel.getLinguisticResourceType(interfaceId).getLIFactory();
			Collection<String> interfaceProperties = liFact.getInterfaceProperties();
			
			//List of the interface properties and their values
			Element interfaceNode = XMLHelp.newElement(dataElement, "lingInterface");
			interfaceNode.setAttribute("interfaceId", interfaceId);
			for (String propId : interfaceProperties) {
				Element inteterfacePropNode = XMLHelp.newElement(interfaceNode, "interfaceProp");
				inteterfacePropNode.setAttribute("propId", propId);
				String propValue = liFact.getPropertyValue(propId);
				inteterfacePropNode.setAttribute("propValue", propValue);
				String description = liFact.getPropertyDescription(propId);
				inteterfacePropNode.setAttribute("propDescr", description);
			}
			//List of the instance properties and their values
			Element instancesNode = XMLHelp.newElement(dataElement, "lingInstances");
			Collection<String> instancesIDs = lingModel.getInstancesIDs();
			Collection <String> instanceProperties = liFact.getInstanceProperties();
			for(String instanceId : instancesIDs){
				String interfaceIdFromInstance 
					= lingModel.getLinguisticResource(instanceId).getLinguisticInterfaceID();
				if(!interfaceIdFromInstance.equals(interfaceId))
					continue;
				Element instanceNode = XMLHelp.newElement(instancesNode, "lingInstance");
				instanceNode.setAttribute("instanceId", instanceId);
				LinguisticResource lRes = lingModel.getLinguisticResource(instanceId);
				for(String instPropId : instanceProperties){
					String instPropValue = lRes.getPropertyValue(instPropId);
					Element instancePropNode = XMLHelp.newElement(instanceNode, "instanceProp");
					instancePropNode.setAttribute("propId", instPropId);
					instancePropNode.setAttribute("propValue", instPropValue);
					String propDescr = liFact.getPropertyDescription(instPropId);
					instancePropNode.setAttribute("propDescr", propDescr);
				}
			}
			
			//a template of a null instance
			Element instanceTempaleNode = XMLHelp.newElement(dataElement, "lingInstanceTeplate");
			for(String instPropId : instanceProperties){
				Element instancePropNode = XMLHelp.newElement(instanceTempaleNode, "instanceProp");
				instancePropNode.setAttribute("propId", instPropId);
				String propDescr = liFact.getPropertyDescription(instPropId);
				instancePropNode.setAttribute("propDescr", propDescr);
			}
			
		}catch (PropertyNotFoundException e){
			return servletUtilities.createExceptionResponse(getLingInterfaceListRequest, e.getMessage());
		}
		return response;
	}
	
	private Response updateLingInstanceId(String oldInstanceId, String newInstanceId) {
		XMLResponseREPLY response;
		
		response = ServletUtilities.getService().createReplyResponse(updateLingInstanceIdRequest, 
				RepliesStatus.ok);
		LingModel lingModel = LinguisticWatermarkManager.getLinguisticModel();
		LinguisticResource lRes = lingModel.getLinguisticResource(oldInstanceId);
		if(lRes == null){
			return servletUtilities.createExceptionResponse(updateLingInstanceIdRequest, 
					"there is no linguistic resource with the following id: "+oldInstanceId);
		}
		lingModel.changeInstanceName(oldInstanceId, newInstanceId);
		LinguisticWatermarkManager.save();
		
		Element dataElement = response.getDataElement();
		Element updatedInstanceIdNode = XMLHelp.newElement(dataElement, "updatedInstanceId");
		updatedInstanceIdNode.setAttribute("oldInstanceId", oldInstanceId);
		updatedInstanceIdNode.setAttribute("newInterfaceId", newInstanceId);
		
		return response;
	}
	
	private Response updateLingInstancePropValue(String instanceId, String interfaceId, String propId, 
			String propValue, boolean isInterfaceProp){
		XMLResponseREPLY response;
		
		response = ServletUtilities.getService().createReplyResponse(updateLingInstancePropValueRequest, 
				RepliesStatus.ok);
		LingModel lingModel = LinguisticWatermarkManager.getLinguisticModel();
		
		if(isInterfaceProp == true){
			ArrayList <String> instancesWithProblem = new ArrayList<String>();
			try{
				lingModel.getLinguisticResourceType(interfaceId).setProperty(propId, propValue);
				//now we must unload an load all the instance of this interface which were previously loaded
				Collection <LinguisticResource>lingRess = lingModel.getLinguisticResources();
				for(LinguisticResource lingRes : lingRess){
					if(lingRes.getLinguisticInterfaceID().equals(interfaceId) 
							&& lingRes.getLinguisticInterface() != null){
						lingRes.unloadLinguisticInterface();
						try{
							lingRes.loadLinguisticInterface();
						} catch (LinguisticInterfaceLoadException e) {
							lingRes.unloadLinguisticInterface();
							instancesWithProblem.add(lingRes.getId());
						}
					}
				}
				if(instancesWithProblem.size() != 0){
					return servletUtilities.createExceptionResponse(updateLingInstancePropValueRequest, 
							"There was a problem in loading some linguistic resources");
				}
			} catch (PropertyNotFoundException e) {
				return servletUtilities.createExceptionResponse(updateLingInstancePropValueRequest, 
						"The linguistic resource with the following id: "+instanceId+ " has no "
								+propId+" property "+e);
			}
		}
		else{
			LinguisticResource lRes = lingModel.getLinguisticResource(instanceId);
			if(lRes == null){
				return servletUtilities.createExceptionResponse(updateLingInstancePropValueRequest, 
						"there is no linguistic resource with the following id: "+instanceId);
			}try{
				lRes.getPropertyValue(propId); // this is used only to see if the property exist
				lRes.setProperty(propId, propValue);
				if(lRes.getLinguisticInterface() != null){
					lRes.unloadLinguisticInterface();
					lRes.loadLinguisticInterface();
				}
			} catch (PropertyNotFoundException e) {
				lRes.unloadLinguisticInterface();
				return servletUtilities.createExceptionResponse(updateLingInstancePropValueRequest, 
						"The linguistic resource with the following id: "+instanceId+ " has no "
								+propId+" property "+e);
			} catch (LinguisticInterfaceLoadException e) {
				lRes.unloadLinguisticInterface();
				return servletUtilities.createExceptionResponse(updateLingInstancePropValueRequest, 
						"There was a problem in loading some linguistic resources");
			}
		}
		
		LinguisticWatermarkManager.save();
		
		Element dataElement = response.getDataElement();
		Element updatedInstanceIdNode = XMLHelp.newElement(dataElement, "updatedInstanceId");
		updatedInstanceIdNode.setAttribute("instanceId", instanceId);
		updatedInstanceIdNode.setAttribute("propId", propId);
		updatedInstanceIdNode.setAttribute("propValue", propValue);
		
		return response;
	}
	
	private Response createLingInstance(String instanceId, String interfaceId) {
		XMLResponseREPLY response;
		
		response = ServletUtilities.getService().createReplyResponse(createLingInstanceRequest, 
				RepliesStatus.ok);
		LingModel lingModel = LinguisticWatermarkManager.getLinguisticModel();
		LinguisticResource lRes = lingModel.getLinguisticResource(instanceId);
		if(lRes != null){
			return servletUtilities.createExceptionResponse(updateLingInstanceIdRequest, 
					"cannot create a Linguistic Resource with the following id: "+instanceId
					+" because there is already one");
		}
		lRes = new LinguisticResource(instanceId);
		lRes.setLinguisticInterfaceID(interfaceId);
		Collection<LIFactory> liFactories = lingModel.getLIFactoriesLoaded();
		boolean found = false;
		for(LIFactory liFactory : liFactories){
			if(liFactory.getId().equals(interfaceId)){
				found = true;
				lRes.setLinguisticInterfaceFactory(liFactory);
				lRes.setLinguisticInterfaceID(interfaceId);
				lingModel.addLinguisticResourse(lRes);
				LinguisticWatermarkManager.save();
				break;
			}
		}
		if(found == false)
			return servletUtilities.createExceptionResponse(updateLingInstanceIdRequest, 
					"cannot create a Linguistic Resource with the following id: "+instanceId
					+" because the interface "+interfaceId + "does not exist");
		
		Element dataElement = response.getDataElement();
		Element updatedInstanceIdNode = XMLHelp.newElement(dataElement, "createdInstanceId");
		updatedInstanceIdNode.setAttribute("instanceId", instanceId);
		updatedInstanceIdNode.setAttribute("interfaceId", interfaceId);
		return response;
	}
	
	private Response removeLingInstance(String instanceId, String interfaceId) {
		XMLResponseREPLY response;
		
		response = ServletUtilities.getService().createReplyResponse(removeLingInstanceRequest, 
				RepliesStatus.ok);
		LingModel lingModel = LinguisticWatermarkManager.getLinguisticModel();
		LinguisticResource lRes = lingModel.getLinguisticResource(instanceId);
		if(lRes == null){
			return servletUtilities.createExceptionResponse(updateLingInstanceIdRequest, 
					"cannot remove the Linguistic Resource with the following id: "+instanceId
					+" because it doesn't exist");
		}
		lingModel.removeLinguisticResource(instanceId);
		LinguisticWatermarkManager.save();
		
		Element dataElement = response.getDataElement();
		Element updatedInstanceIdNode = XMLHelp.newElement(dataElement, "removedInstance");
		updatedInstanceIdNode.setAttribute("instanceId", instanceId);
		updatedInstanceIdNode.setAttribute("interfaceId", interfaceId);
		return response;
	}


	@Override
	protected Logger getLogger() {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	protected Response getPreCheckedResponse(String request) throws HTTPParameterUnspecifiedException {
		// TODO Auto-generated method stub
		return null;
	}
	
	
}


